package com.apop.common.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apop.common.component.HttpSender;
import com.apop.common.component.SpringUtil;
import com.apop.common.config.action.Action;
import com.apop.common.config.action.ActionManager;
import com.apop.common.mapper.mapper1.OneMapper;
import com.apop.common.model.CodeMsg;
import com.apop.common.model.Result;
import com.apop.hrss.home.componet.ParamsProcessor;
import com.apop.hrss.home.componet.PostProcessor;
import com.apop.hrss.home.util.SQLUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author Jiayi Zheng
 * @version V1.0
 * @ClassName UniController
 * @date 2021/11/10 15:35
 * @Description: 数据请求统一路由
 */
@RestController
@RequestMapping("/api")
@Slf4j
public class OneController {

    @Autowired
    private OneMapper oneMapper;

    @Autowired
    private PostProcessor postProcessor;

    @Autowired
    Environment env;

    @GetMapping
    public Result test() {
        return Result.success("v2.1");
    }

    /**
     * 通用数据集接口
     *
     * @param param
     * @param response
     * @return
     */
    @ApiOperation(value = "通用数据集接口", notes = "通用数据集接口not", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "param", value = "参数")
    })
//    @Cacheable(value = "ehcache")
    @PostMapping("/dataSet")
    public Result dataSet(@RequestBody Map param,HttpServletRequest request, HttpServletResponse response) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        // 1.获取请求体中的serviceId
        Integer serviceId = (Integer) param.get("serviceId");
        if (serviceId == null) {
            return Result.error(CodeMsg.ACTION_ERROR);
        }
        Map<String, Object> params = (Map) param.get("params");

        ActionManager actionManager = (ActionManager) SpringUtil.getBean("actionManager");
        List<Action> actionList = actionManager.getActionList();
        Action findAction = new Action();
        findAction.setServiceId(serviceId);

        List<Map> retList = new ArrayList<>();

        // 通过serviceId找到对应action(action在容器启动后预加载)
        int index = Collections.binarySearch(actionList, findAction);
        if (index < 0) {
            return Result.error(CodeMsg.ACTION_ERROR);
        }
        Action action = actionList.get(index);
        if (action.getType() == null) {
            return Result.error(CodeMsg.RESULT_TYPE_NOT_FOUND);
        }

        // 入参处理
        List<String> paramProcessors = action.getParamProcessors();
        if(paramProcessors!=null){
            for(String methodStr : paramProcessors){
                // 获得不同处理器的方法
                ParamsProcessor postProcessor = SpringUtil.getBean(ParamsProcessor.class);
                Method method = postProcessor.getClass().getMethod(methodStr, Action.class,Map.class);
                params = (Map)method.invoke(postProcessor,  action,params);
            }
        }

        // 判断类型
        switch (action.getType()) {
            case "mock":// 假数据处理
                String jsonStr = actionManager.getMockData().get(action.getServiceId());
                if (jsonStr == null) {
                    return Result.error(CodeMsg.MOCK_DATA_NOT_FOUND);
                }
                if ("object".equals(action.getResultType())) {
                    JSONObject jsonObject = JSON.parseObject(jsonStr);
                    return Result.success(jsonObject);
                } else if ("list".equals(action.getResultType())) {
                    JSONArray jsonArray = JSON.parseArray(jsonStr);
                    return Result.success(jsonArray);
                } else if ("page".equals(action.getResultType())) {
                    JSONArray jsonArray = JSON.parseArray(jsonStr);
                    JSONObject pageResult = new JSONObject();
                    pageResult.put("total", 100);
                    pageResult.put("pageSize", 10);
                    pageResult.put("pageNum", 1);
                    pageResult.put("list", jsonArray);
                    // 待完善
                    return Result.success(pageResult);
                } else {
                    return Result.error(CodeMsg.RESULT_TYPE_NOT_FOUND);
                }

            case "db":// db

                String origin = action.getSql();
                // TODO sql 执行前处理
                if (null != action.getParams()) {
                    String paramStr = action.getParams();
                    List<Object> list = new ArrayList<>();
                    String[] part = paramStr.split(",");
                    for (String paramPart : part) {
                        if (paramPart.equals("tableName")) {
                            origin = origin.replace("#", String.valueOf(params.get(paramPart)));
                        } else {
                            list.add(params.get(paramPart));
                        }
                    }
                    origin = SQLUtil.replaceWithParams(list, origin);
                }

                // 执行原始查询
                retList = oneMapper.executeQuery(origin);
                break;
            case "http"://http 业务专属 需要改造

                String url = action.getTargetUrl();
                String urlPrefix = "";
                Integer mode = action.getMode();
                if (mode == 1) {
                    urlPrefix = env.getProperty("backend.url.livebos");
                } else if (mode == 2) {
                    urlPrefix = env.getProperty("backend.url.bizproccessor");
                }
                url = url.replaceFirst("\\{url\\}", urlPrefix);

                Result result = (Result) HttpSender.sendRequest(url, params, action.getHttpMethod());
                retList = (List<Map>) result.getData();
        }

        // 空值处理
        if (retList.isEmpty()) {
            return Result.success(retList);
        }
        // 数据后处理
        if (action.getPostProcessors() != null) {
            List<String> postProcessors = action.getPostProcessors();
            for (String methodStr : postProcessors) {
                PostProcessor postProcessor = SpringUtil.getBean(PostProcessor.class);
                Method method = postProcessor.getClass().getMethod(methodStr, List.class, Action.class);
                retList = (List<Map>) method.invoke(postProcessor, retList, action);
            }
        }

        Result result = Result.success(retList);
        request.setAttribute("result",result);
        return result;
    }

    /**
     * 获取用户信息
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/user_info")
    @ResponseBody
    public Result userInfo(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        // ticket 存入session 如果是集群部署则要用redis
        log.debug("请求 userInfo");
        log.debug("sessionId {} ", session.getId());
        Boolean isLogin = (Boolean) session.getAttribute("isLogin");
        if (isLogin == null || !isLogin) {

            return Result.fail(500, "未登陆！");
        }
        String personalInfo = (String) session.getAttribute("personalInfo");
        if (personalInfo == null) {
            return Result.fail(500, "获取用户信息失败");
        }
        // 转换成json返回给前端
        JSONObject jsonObject = JSON.parseObject(personalInfo);
        return Result.success(jsonObject);
    }

    /**
     * 通用的表单提交
     *
     * @param param
     * @param response
     * @return
     */
    @PostMapping("/submit")
    public Result submitTable(@RequestBody Map param, HttpServletResponse response) {
        String tableName = (String) param.get("tableName");
        Map<String, Object> columns = (Map) param.get("columns");
        int rs = 0;
        try {
            rs = oneMapper.commonInsert(String.valueOf(SQLUtil.commonInsertSql(columns, tableName)));
            if (rs > 0) {
                return Result.success(null);
            } else {
                return Result.success("插入失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(500, "插入异常 " + e.getMessage());
        }
    }

    /**
     * 清除全部缓存
     *
     * @param response
     * @return
     */
    @PostMapping("/clearAllCache")
    @CacheEvict(value = "ehcache", allEntries = true)
    public Result clearAllCache(HttpServletResponse response) {
        return Result.success("操作成功");
    }

}

